
#include "serial.h"

/**
							基于GD32芯片设计的简易串口框架
		说明:
		1、串口接收开启DMA并结合空闲中断获取不定长数据,串口数据通过DMA输出数据
		2、框架基于GD32F303+标准库进行的调试，目前只支持三路串口，如果想扩展串口，
			 简单添加部分代码即可
		3、框架中断调用的串口函数，如下:
			 void HAL_UART_TxCpltCallback(uint32_t usart)
			 void HAL_UART_RxCpltCallback(uint32_t usart)
			 void HAL_UART_ErrorCallback(uint32_t usart)
		 
			 
		 使用说明:(框架源码在serials目录下)
		 1、使能打开硬件对应串口模块，宏定义选择打开，例如开启串口1，修改为 #define USART1_ENABLE 1
		 2、必须调用serial_init()函数对串口资源进行初始化，并开启串口接收数据
		 3、用户上层代码选择对serial_process_callback()函数进行覆盖定义，需循环调用该函数对串口数据进行收发处理
		 4、用户上层可调用serial_write()向串口发送缓冲区中写入数据，需指定串口ID
		 5、用户上层可调用serial_read()读取串口接收缓冲区中数据，需指定串口ID
		 
			 
**/

/// 串口相关收发缓冲区设置和定义，如果新加串口，对应定义即可
#if ( USART1_ENABLE==1 )
	#define USART1_TX_BUFF_SIZE 		1024
	#define USART1_RX_BUFF_SIZE 		1024
	#define USART1_TX_DMA_BUFF_SIZE	512
	#define USART1_RX_DMA_BUFF_SIZE 128
	static uint8_t usart1_tx_buff[USART1_TX_BUFF_SIZE];
	static uint8_t usart1_rx_buff[USART1_RX_BUFF_SIZE];
	static uint8_t usart1_tx_dma_buff[USART1_TX_DMA_BUFF_SIZE];
	static uint8_t usart1_rx_dma_buff[USART1_RX_DMA_BUFF_SIZE];
	static awesome_usart awesome_usart1;   /// 串口数据操作对象
	Serial serial1;
#endif

#if ( USART2_ENABLE==1 )
	#define USART2_TX_BUFF_SIZE 		1024
	#define USART2_RX_BUFF_SIZE 		1024
	#define USART2_TX_DMA_BUFF_SIZE	512
	#define USART2_RX_DMA_BUFF_SIZE 128
	static uint8_t usart2_tx_buff[USART2_TX_BUFF_SIZE];
	static uint8_t usart2_rx_buff[USART2_RX_BUFF_SIZE];
	static uint8_t usart2_tx_dma_buff[USART2_TX_DMA_BUFF_SIZE];
	static uint8_t usart2_rx_dma_buff[USART2_RX_DMA_BUFF_SIZE];
	static awesome_usart awesome_usart2;
	Serial serial2;
#endif

#if ( USART3_ENABLE==1 )
	#define USART3_TX_BUFF_SIZE 		1024
	#define USART3_RX_BUFF_SIZE 		1024
	#define USART3_TX_DMA_BUFF_SIZE	512
	#define USART3_RX_DMA_BUFF_SIZE 128
	static uint8_t usart3_tx_buff[USART3_TX_BUFF_SIZE];
	static uint8_t usart3_rx_buff[USART3_RX_BUFF_SIZE];
	static uint8_t usart3_tx_dma_buff[USART3_TX_DMA_BUFF_SIZE];
	static uint8_t usart3_rx_dma_buff[USART3_RX_DMA_BUFF_SIZE];
	static awesome_usart awesome_usart3;
	
	Serial serial3;
#endif

#if ( USB_USART_ENABLE==1 )
	#define USB_TX_BUFF_SIZE 		2048
	#define USB_RX_BUFF_SIZE 		1024
	#define USB_TX_DMA_BUFF_SIZE	512
	#define USB_RX_DMA_BUFF_SIZE  128
	static uint8_t usb_tx_buff[USB_TX_BUFF_SIZE];
	static uint8_t usb_rx_buff[USB_RX_BUFF_SIZE];
	static uint8_t usb_tx_dma_buff[USB_TX_DMA_BUFF_SIZE];
	static awesome_usart awesome_usart_usb;	
	extern USBD_HandleTypeDef hUsbDeviceFS;
	
	Serial usb_serial;
#endif

Serial* serials[USART_MAX_NUM] = { (void*)0, (void*)0, (void*)0, (void*)0 };   // 串口上层对象数组

///////////////////////////////////////////////////////////////////

///串口硬件初始化波特率等参数
static void usart_config(uint32_t usart_periph, uint32_t baudval, uint32_t wlen, uint32_t paritycfg, uint32_t stblen)
{
	usart_enable(usart_periph);
	usart_word_length_set(usart_periph, wlen);
	usart_stop_bit_set(usart_periph, stblen);
	usart_baudrate_set(usart_periph, baudval);
	usart_parity_config(usart_periph, paritycfg);
	
	usart_hardware_flow_cts_config(usart_periph, USART_CTS_DISABLE);
}

///串口底层硬件初始化，用户可针对修改串口参数
void serial_hw_init(void)
{
	//gpio_afio_deinit();  //为了防止和其他硬件配置冲突，建议在硬件初始化之前调用该函数
	rcu_periph_clock_enable(RCU_AF);      //开启引脚多功能时钟
	rcu_periph_clock_enable(RCU_DMA0);    //开启DMA0时钟 
	
	#if ( USART1_ENABLE==1 )
	//设置时钟，波特率，数据位，停止位，校验位等参数
	rcu_periph_clock_enable(RCU_USART0);
	
	//PA9-TX,PA10-RX
	rcu_periph_clock_enable(RCU_GPIOA);
	gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_9);
	gpio_init(GPIOA, GPIO_MODE_IPU, GPIO_OSPEED_10MHZ, GPIO_PIN_10);
	
	usart_config(USART0, 115200, USART_WL_8BIT, USART_PM_NONE, USART_STB_1BIT);
	
	//开启DMA
	usart_dma_receive_config(USART0, USART_DENR_ENABLE);  
	usart_dma_transmit_config(USART0, USART_DENT_ENABLE);
	
	//设置中断优先级和使能中断
	NVIC_SetPriority(USART0_IRQn, 5);
	NVIC_EnableIRQ(USART0_IRQn);
	
	NVIC_SetPriority(DMA0_Channel3_IRQn, 6);
	NVIC_EnableIRQ(DMA0_Channel3_IRQn);
	NVIC_SetPriority(DMA0_Channel4_IRQn, 6);
	NVIC_EnableIRQ(DMA0_Channel4_IRQn);
	#endif
	
	#if ( USART2_ENABLE==1 )
	rcu_periph_clock_enable(RCU_USART1);
	
	//PA2-TX,PA3-RX
	rcu_periph_clock_enable(RCU_GPIOA);
	gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_2);
	gpio_init(GPIOA, GPIO_MODE_IPU, GPIO_OSPEED_10MHZ, GPIO_PIN_3);
	
	usart_config(USART1, 115200, USART_WL_8BIT, USART_PM_NONE, USART_STB_1BIT);
	
	usart_dma_receive_config(USART1, USART_DENR_ENABLE);  
	usart_dma_transmit_config(USART1, USART_DENT_ENABLE);
	
	NVIC_SetPriority(USART1_IRQn, 5);
	NVIC_EnableIRQ(USART1_IRQn);
	
	NVIC_SetPriority(DMA0_Channel5_IRQn, 7);
	NVIC_EnableIRQ(DMA0_Channel5_IRQn);
	NVIC_SetPriority(DMA0_Channel6_IRQn, 7);
	NVIC_EnableIRQ(DMA0_Channel6_IRQn);
	#endif
	
	#if ( USART3_ENABLE==1 )
	rcu_periph_clock_enable(RCU_USART2);
	
	//PB10-TX,PB11-RX
	rcu_periph_clock_enable(RCU_GPIOA);
	gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_10);
	gpio_init(GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_10MHZ, GPIO_PIN_11);
	
	usart_config(USART2, 115200, USART_WL_8BIT, USART_PM_NONE, USART_STB_1BIT);
	
	usart_dma_receive_config(USART2, USART_DENR_ENABLE);  
	usart_dma_transmit_config(USART2, USART_DENT_ENABLE);
	
	NVIC_SetPriority(USART2_IRQn, 5);
	NVIC_EnableIRQ(USART2_IRQn);
	
	NVIC_SetPriority(DMA0_Channel1_IRQn, 8);
	NVIC_EnableIRQ(DMA0_Channel1_IRQn);
	NVIC_SetPriority(DMA0_Channel2_IRQn, 8);
	NVIC_EnableIRQ(DMA0_Channel2_IRQn);
	#endif
}

/// 初始化串口资源，需要使用串口资源，必须调用该函数初始化
void serial_init(void)
{
	serial_hw_init();
#if ( USART1_ENABLE==1 )
	awesome_usart_init(&awesome_usart1, usart1_rx_buff, USART1_RX_BUFF_SIZE, usart1_tx_buff, USART1_TX_BUFF_SIZE);
	serial1.id = SERIAL_ID_1;
	serial1.send_status = SERIAL_SEND_STATUS_NONE;
	serial1.receive_status = SERIAL_SEND_STATUS_NONE;
	serial1.huart = (void*)USART0;
	serial1.pawesome_usart = &awesome_usart1;
	serial1.ptx = usart1_tx_buff;
	serial1.prx = usart1_rx_buff;
	serial1.pdmatx = usart1_tx_dma_buff;
	serial1.pdmarx = usart1_rx_dma_buff;
	serial1.tx_max_size = USART1_TX_BUFF_SIZE;
	serial1.rx_max_size = USART1_RX_BUFF_SIZE;
	serial1.tx_max_dma_size = USART1_TX_DMA_BUFF_SIZE;
	serial1.rx_max_dma_size = USART1_RX_DMA_BUFF_SIZE;
	serials[0] = &serial1;
	open_serial_receive(&serial1);
#endif
	
#if ( USART2_ENABLE==1 )
	awesome_usart_init(&awesome_usart2, usart2_rx_buff, USART2_RX_BUFF_SIZE, usart2_tx_buff, USART2_TX_BUFF_SIZE);
	serial2.id = SERIAL_ID_2;
	serial2.send_status = SERIAL_SEND_STATUS_NONE;
	serial2.receive_status = SERIAL_SEND_STATUS_NONE;
	serial2.huart = (void*)USART1;
	serial2.pawesome_usart = &awesome_usart2;
	serial2.ptx = usart2_tx_buff;
	serial2.prx = usart2_rx_buff;
	serial2.pdmatx = usart2_tx_dma_buff;
	serial2.pdmarx = usart2_rx_dma_buff;
	serial2.tx_max_size = USART2_TX_BUFF_SIZE;
	serial2.rx_max_size = USART2_RX_BUFF_SIZE;
	serial2.tx_max_dma_size = USART2_TX_DMA_BUFF_SIZE;
	serial2.rx_max_dma_size = USART2_RX_DMA_BUFF_SIZE;
	serials[1] = &serial2;
	open_serial_receive(&serial2);
#endif
	
#if ( USART3_ENABLE==1 )
	awesome_usart_init(&awesome_usart3, usart3_rx_buff, USART3_RX_BUFF_SIZE, usart3_tx_buff, USART3_TX_BUFF_SIZE);
	serial3.id = SERIAL_ID_3;
	serial3.send_status = SERIAL_SEND_STATUS_NONE;
	serial3.receive_status = SERIAL_SEND_STATUS_NONE;
	serial3.huart = (void*)USART2;
	serial3.pawesome_usart = &awesome_usart3;
	serial3.ptx = usart3_tx_buff;
	serial3.prx = usart3_rx_buff;
	serial3.pdmatx = usart3_tx_dma_buff;
	serial3.pdmarx = usart3_rx_dma_buff;
	serial3.tx_max_size = USART3_TX_BUFF_SIZE;
	serial3.rx_max_size = USART3_RX_BUFF_SIZE;
	serial3.tx_max_dma_size = USART3_TX_DMA_BUFF_SIZE;
	serial3.rx_max_dma_size = USART3_RX_DMA_BUFF_SIZE;
	serials[2] = &serial3;
	open_serial_receive(&serial3);
#endif

#if ( USB_USART_ENABLE==1 )
	awesome_usart_init(&awesome_usart_usb, usb_rx_buff, USB_RX_BUFF_SIZE, usb_tx_buff, USB_TX_BUFF_SIZE);
	usb_serial.id = SERIAL_ID_USB;
	usb_serial.send_status = SERIAL_SEND_STATUS_NONE;
	usb_serial.receive_status = SERIAL_SEND_STATUS_NONE;
	usb_serial.huart = (void*)&hUsbDeviceFS;
	usb_serial.pawesome_usart = &awesome_usart_usb;
	usb_serial.ptx = usb_tx_buff;
	usb_serial.prx = usb_rx_buff;
	usb_serial.pdmatx = usb_tx_dma_buff;
	usb_serial.pdmarx = NULL;
	usb_serial.tx_max_size = USB_TX_BUFF_SIZE;
	usb_serial.rx_max_size = USB_RX_BUFF_SIZE;
	usb_serial.tx_max_dma_size = USB_TX_DMA_BUFF_SIZE;
	usb_serial.rx_max_dma_size = 0;
	serials[3] = &usb_serial;
#endif
}

/// 收发处理函数，上层定时调用，用户可以覆盖
/// 判断发送数据是否有效，有效则发送新的一帧数据
/// 读取串口接收缓冲区中的数据进行处理
__weak void serial_process_callback(void)
{	
	uint8_t i = 0;
	for( ; i<USART_MAX_NUM; ++i )
	{
		if( serials[i]!=(void*)0 )
		{
			SERIAL_ID id = serials[i]->id;
			switch(id)
			{
				case SERIAL_ID_1:
					break;
				case SERIAL_ID_2:
					break;
				case SERIAL_ID_3:
					break;
				case SERIAL_ID_USB:
					break;
				default:
					break;
			}	
			
			open_usart_send(serials[i]);			
		}
	}
}


/// 串口收发上层调用函数 ///
/// 往串口发送缓冲区中写入数据
void serial_write(SERIAL_ID id, uint8_t* data, uint32_t len)
{
	Serial* ps = get_serial_by_id(id);
	if((void*)0==ps) return;
	ps->pawesome_usart->writes(ps->pawesome_usart, data, len);
}

/// 读取串口接收数据,返回读取的有效数据长度
uint32_t serial_read(SERIAL_ID id, uint8_t* data, uint32_t len)
{
	Serial* ps = get_serial_by_id(id);
	if((void*)0==ps) return 0;
	return ps->pawesome_usart->reads(ps->pawesome_usart, data, len);
}
////////////////////////////////////////////////////////////////////


/// 通过串口实例获取serial对象，用户可根据实际使用串口进行修改
Serial* get_serial(void* huart)
{	
	#if ( USART1_ENABLE==1 )
		if( (void*)USART0==huart && serial1.huart==huart )
			return &serial1;
	#endif
	
	#if ( USART2_ENABLE==1 )
		if( (void*)USART1==huart && serial2.huart==huart )
			return &serial2;
	#endif
		
	#if ( USART3_ENABLE==1 )
		if( (void*)USART2==huart && serial3.huart==huart )
			return &serial3;
	#endif
		
	#if ( USB_USART_ENABLE==1 )
		if( &hUsbDeviceFS==(USBD_HandleTypeDef*)huart && usb_serial.huart==huart)
			return &usb_serial;
	#endif
	return (void*)0;
}

/// 通过串口实例获取serial对象，用户可根据实际使用串口进行修改
Serial* get_serial_by_id(SERIAL_ID id)
{
	
	#if ( USART1_ENABLE==1 )
		if( id==SERIAL_ID_1 )
			return &serial1;
	#endif
	
	#if ( USART2_ENABLE==1 )
		if( id==SERIAL_ID_2 )
			return &serial2;
	#endif
		
	#if ( USART3_ENABLE==1 )
		if( id==SERIAL_ID_3 )
			return &serial3;
	#endif
		
	#if ( USB_USART_ENABLE==1 )
		if( id==SERIAL_ID_USB )
			return &usb_serial;
	#endif
	return (void*)0;
}

/// 串口DMA接收配置
static void usart_receive_dma_config(Serial* ps)
{
	dma_parameter_struct dma_struct_i;
	uint32_t dma_periph;
	dma_channel_enum channelx;
	
	dma_struct_i.memory_addr = (uint32_t)ps->pdmarx;
	dma_struct_i.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
	dma_struct_i.memory_width = DMA_MEMORY_WIDTH_8BIT;
	
	dma_struct_i.direction = DMA_PERIPHERAL_TO_MEMORY;
	dma_struct_i.priority = DMA_PRIORITY_LOW;
	
	dma_struct_i.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
	dma_struct_i.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
	dma_struct_i.periph_addr = (uint32_t)(&(USART_DATA((uint32_t)(ps->huart))));
	
	dma_struct_i.number = ps->rx_max_dma_size;
	
	if( ps->huart==(void*)USART0 )
	{
		dma_periph = DMA0;
		channelx = DMA_CH4;
	}else if( ps->huart==(void*)USART1 )
	{
		dma_periph = DMA0;
		channelx = DMA_CH5;
	}else if( ps->huart==(void*)USART2 )
	{
		dma_periph = DMA0;
		channelx = DMA_CH2;
	}
	
	dma_deinit(dma_periph, channelx);
	
	dma_init(dma_periph, channelx, &dma_struct_i);
	dma_circulation_disable(dma_periph, channelx);
	dma_interrupt_flag_clear(dma_periph, channelx, DMA_INT_FLAG_FTF|DMA_INT_FLAG_ERR);
	dma_interrupt_enable(dma_periph, channelx, DMA_INT_FTF|DMA_INT_ERR); //开启DMA传输完成和错误中断
	dma_channel_enable(dma_periph, channelx);
	
	//开启串口
	usart_dma_receive_config((uint32_t)(ps->huart), USART_DENR_ENABLE); 
	usart_receive_config((uint32_t)(ps->huart), USART_RECEIVE_ENABLE);
	usart_interrupt_flag_clear((uint32_t)(ps->huart), USART_INT_FLAG_RBNE);
	usart_interrupt_enable((uint32_t)(ps->huart), USART_INT_RBNE);
	usart_interrupt_enable((uint32_t)(ps->huart), USART_INT_IDLE);
	usart_interrupt_enable((uint32_t)(ps->huart), USART_INT_ERR);
	usart_interrupt_enable((uint32_t)(ps->huart), USART_INT_PERR);
	
}

/// 串口发送DMA配置
static void usart_send_dma_config(Serial* ps, uint32_t len)
{
	dma_parameter_struct dma_struct_i;
	uint32_t dma_periph;
	dma_channel_enum channelx;
	
	dma_struct_i.memory_addr = (uint32_t)ps->pdmatx;
	dma_struct_i.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
	dma_struct_i.memory_width = DMA_MEMORY_WIDTH_8BIT;
	
	dma_struct_i.direction = DMA_MEMORY_TO_PERIPHERAL;
	dma_struct_i.priority = DMA_PRIORITY_LOW;
	
	dma_struct_i.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
	dma_struct_i.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
	dma_struct_i.periph_addr = (uint32_t)(&(USART_DATA((uint32_t)(ps->huart))));
	
	dma_struct_i.number = len;
	
	if( ps->huart==(void*)USART0 )
	{
		dma_periph = DMA0;
		channelx = DMA_CH3;
	}else if( ps->huart==(void*)USART1 )
	{
		dma_periph = DMA0;
		channelx = DMA_CH6;
	}else if( ps->huart==(void*)USART2 )
	{
		dma_periph = DMA0;
		channelx = DMA_CH1;
	}
	
	dma_deinit(dma_periph, channelx);
	
	dma_init(dma_periph, channelx, &dma_struct_i);
	dma_circulation_disable(dma_periph, channelx);
	dma_interrupt_flag_clear(dma_periph, channelx, DMA_INT_FLAG_FTF|DMA_INT_FLAG_ERR);
	dma_interrupt_enable(dma_periph, channelx, DMA_INT_FTF|DMA_INT_ERR); //开启DMA传输完成和错误中断
	//开启串口
	usart_dma_transmit_config((uint32_t)(ps->huart), USART_DENT_ENABLE);
	usart_transmit_config((uint32_t)(ps->huart), USART_TRANSMIT_ENABLE);
	usart_interrupt_flag_clear((uint32_t)(ps->huart), USART_INT_FLAG_TC);
	usart_interrupt_disable((uint32_t)(ps->huart), USART_INT_TC);
	dma_channel_enable(dma_periph, channelx);
}

/// 开启串口接收，DMA+空闲中断方式
void open_serial_receive(Serial* ps)
{
	switch(ps->id)
	{
		case SERIAL_ID_1:
			usart_receive_dma_config(ps);
			break;
		case SERIAL_ID_2:
			usart_receive_dma_config(ps);
			break;
		case SERIAL_ID_3:
			usart_receive_dma_config(ps);
			break;
		default: 
			break;
	}
}

/// 开启串口发送，DMA方式发送，发送完成，中断中置位发送完成标志
void open_usart_send(Serial* ps)
{
	if( ps->send_status!=SERIAL_SEND_STATUS_SENDING )
	{
		uint32_t len = ps->pawesome_usart->low_get_write_buff(ps->pawesome_usart, ps->pdmatx, ps->tx_max_dma_size);
		if( len>0 )
		{
			usart_send_dma_config(ps, len);
			ps->send_status = SERIAL_SEND_STATUS_SENDING;
		}
	}
}


////////////////////////////////////////////////////////////////////////////////
///           中断函数调用           ///

/// 串口发送中断完成
void HAL_UART_TxCpltCallback(uint32_t huart)
{	
	Serial* ps = get_serial((void*)huart);
	
	ps->send_status = SERIAL_SEND_STATUS_SUCESS;
	
}

/// 串口接收中断调用(接收缓冲区被填满时调用)
void HAL_UART_RxCpltCallback(uint32_t huart)
{	
	Serial* ps;
	ps = get_serial((void*)huart);
	
	if( ps!=(void*)0 )
	{
		ps->pawesome_usart->low_set_read_buff(ps->pawesome_usart, ps->pdmarx, ps->rx_max_dma_size);
	
		open_serial_receive(ps);   /// 重新打开串口DMA接收
	}
	
}

/// 空闲中断和中断发生错误调用函数，DMA中断错误调用
void HAL_UART_ErrorCallback(uint32_t huart)
{
	uint32_t dma_len = 0;
	Serial* ps = get_serial((void*)huart);
	uint32_t dma_periph;
	dma_channel_enum channelx;
	if( ps->huart==(void*)USART0 )
	{
		dma_periph = DMA0;
		channelx = DMA_CH4;
	}else if( ps->huart==(void*)USART1 )
	{
		dma_periph = DMA0;
		channelx = DMA_CH5;
	}else if( ps->huart==(void*)USART2 )
	{
		dma_periph = DMA0;
		channelx = DMA_CH2;
	}
	
	if( ps!=(void*)0 )
	{
		dma_len = ps->rx_max_dma_size - dma_transfer_number_get(dma_periph, channelx);
		if( dma_len>0 && dma_len!=ps->rx_max_dma_size )   // DMA接收缓冲区没有满，则选择不定长处理
			ps->pawesome_usart->low_set_read_buff(ps->pawesome_usart, ps->pdmarx, dma_len);
	}
	
	open_serial_receive(ps);   /// 重新打开串口DMA接收
		
}

// usb接收调用
void usb_receive_callback(uint8_t* data, uint32_t len)
{
#if ( USB_USART_ENABLE==1 )
	usb_serial.pawesome_usart->low_set_read_buff(usb_serial.pawesome_usart, data, len);
#endif
}

/// 串口中断处理函数
void usart_irq_process(uint32_t usart)
{
	uint32_t dma_periph;
	dma_channel_enum channelx;
	
	if( usart==USART0 )
	{
		dma_periph = DMA0;
		channelx = DMA_CH4;
	}else if( usart==USART1 )
	{
		dma_periph = DMA0;
		channelx = DMA_CH5;
	}else if( usart==USART2 )
	{
		dma_periph = DMA0;
		channelx = DMA_CH2;
	}
	
	//串口发送中断处理
	if( SET==usart_interrupt_flag_get(usart, USART_INT_FLAG_TC) )
	{
		usart_interrupt_flag_clear(usart, USART_INT_FLAG_TC);
		usart_interrupt_disable(usart, USART_INT_TC);
		HAL_UART_TxCpltCallback(usart);
	}
	
	//串口接收中断处理
	if( SET==usart_interrupt_flag_get(usart, USART_INT_FLAG_RBNE) )
	{
		uint32_t data = USART_DATA(usart);
		usart_interrupt_flag_clear(usart, USART_INT_FLAG_RBNE);
		//溢出错误
		if( SET==usart_interrupt_flag_get(usart, USART_INT_FLAG_RBNE_ORERR) )
		{
			//接收数据完成，关闭中断
			usart_receive_config(usart, USART_RECEIVE_DISABLE);
			dma_interrupt_disable(dma_periph, channelx, DMA_INT_FTF);
			dma_interrupt_disable(dma_periph, channelx, DMA_INT_ERR);
			usart_interrupt_disable(usart, USART_INT_RBNE);
			usart_interrupt_disable(usart, USART_INT_IDLE);
			usart_interrupt_disable(usart, USART_INT_ERR);
			usart_interrupt_disable(usart, USART_INT_PERR);
			HAL_UART_ErrorCallback(usart);
		}
	}
	
	//空闲和错误中断处理
	if(SET==usart_interrupt_flag_get(usart, USART_INT_FLAG_IDLE) || \
		 SET==usart_interrupt_flag_get(usart, USART_INT_FLAG_PERR) || \
		 SET==usart_interrupt_flag_get(usart, USART_INT_FLAG_ERR_ORERR) || \
	   SET==usart_interrupt_flag_get(usart, USART_INT_FLAG_ERR_NERR) || \
		 SET==usart_interrupt_flag_get(usart, USART_INT_FLAG_ERR_FERR)){
			uint32_t data = USART_DATA(usart);
			usart_receive_config(usart, USART_RECEIVE_DISABLE);
			dma_interrupt_disable(dma_periph, channelx, DMA_INT_FTF);
			dma_interrupt_disable(dma_periph, channelx, DMA_INT_ERR);
			usart_interrupt_disable(usart, USART_INT_RBNE);
			usart_interrupt_disable(usart, USART_INT_IDLE);
			usart_interrupt_disable(usart, USART_INT_ERR);
			usart_interrupt_disable(usart, USART_INT_PERR);
			HAL_UART_ErrorCallback(usart);
		 }
}

void usart_dma_rx_irq_process(uint32_t usart)
{
	uint32_t dma_periph;
	dma_channel_enum channelx;
	
	if( usart==USART0 )
	{
		dma_periph = DMA0;
		channelx = DMA_CH4;
	}else if( usart==USART1 )
	{
		dma_periph = DMA0;
		channelx = DMA_CH5;
	}else if( usart==USART2 )
	{
		dma_periph = DMA0;
		channelx = DMA_CH2;
	}
	
	if( SET==dma_interrupt_flag_get(dma_periph, channelx, DMA_INT_FLAG_FTF) )
	{
		dma_interrupt_flag_clear(dma_periph, channelx, DMA_INT_FLAG_FTF);
		usart_interrupt_disable(usart, USART_INT_RBNE);
		usart_interrupt_disable(usart, USART_INT_IDLE);
		usart_interrupt_disable(usart, USART_INT_ERR);
		usart_interrupt_disable(usart, USART_INT_PERR);
		dma_interrupt_disable(dma_periph, channelx, DMA_INT_FTF);
		dma_interrupt_disable(dma_periph, channelx, DMA_INT_ERR);
		HAL_UART_RxCpltCallback(usart);
	}
	
	if( SET==dma_interrupt_flag_get(dma_periph, channelx, DMA_INT_FLAG_ERR) )
	{
		dma_interrupt_flag_clear(dma_periph, channelx, DMA_INT_FLAG_ERR);
		usart_interrupt_disable(usart, USART_INT_RBNE);
		usart_interrupt_disable(usart, USART_INT_IDLE);
		usart_interrupt_disable(usart, USART_INT_ERR);
		usart_interrupt_disable(usart, USART_INT_PERR);
		dma_interrupt_disable(dma_periph, channelx, DMA_INT_FTF);
		dma_interrupt_disable(dma_periph, channelx, DMA_INT_ERR);
		HAL_UART_ErrorCallback(usart);
	}
}

void usart_dma_tx_irq_process(uint32_t usart)
{
	uint32_t dma_periph;
	dma_channel_enum channelx;
	
	if( usart==USART0 )
	{
		dma_periph = DMA0;
		channelx = DMA_CH3;
	}else if( usart==USART1 )
	{
		dma_periph = DMA0;
		channelx = DMA_CH6;
	}else if( usart==USART2 )
	{
		dma_periph = DMA0;
		channelx = DMA_CH1;
	}
	
	if( SET==dma_interrupt_flag_get(dma_periph, channelx, DMA_INT_FLAG_FTF) )
	{
		dma_interrupt_flag_clear(dma_periph, channelx, DMA_INT_FLAG_FTF);
		dma_interrupt_disable(dma_periph, channelx, DMA_INT_FTF);
		usart_interrupt_enable(usart, USART_INT_TC);
	}
}


///串口发送接收中断
void USART0_IRQHandler(void)
{
	usart_irq_process(USART0);
}

void USART1_IRQHandler(void)
{
	usart_irq_process(USART1);
}

void USART2_IRQHandler(void)
{
	usart_irq_process(USART2);
}

///串口DMA中断
void DMA0_Channel1_IRQHandler(void)
{
	usart_dma_tx_irq_process(USART2);
}

void DMA0_Channel2_IRQHandler(void)
{
	usart_dma_rx_irq_process(USART2);
}

void DMA0_Channel3_IRQHandler(void)
{
	usart_dma_tx_irq_process(USART0);
}

void DMA0_Channel4_IRQHandler(void)
{
	usart_dma_rx_irq_process(USART0);
}

void DMA0_Channel5_IRQHandler(void)
{
	usart_dma_rx_irq_process(USART1);
}

void DMA0_Channel6_IRQHandler(void)
{
	usart_dma_tx_irq_process(USART1);
}


